package jp.eisbahn.mgapi.auth;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;

/**
 * This class has an ability to build the URL for the authorization.
 * @author Yoichiro Tanaka
 */
public class AuthorizationUrlBuilder {

    /** The URL for authorization for PC and smart-phone device. */
    private static final String MIXI_AUTHORIZATION_URL =
        "https://mixi.jp/connect_authorize.pl?";
    /** The URL for authorization for mobile devices. */
    private static final String MIXI_AUTHORIZATION_MOBILE_URL =
        "http://m.mixi.jp/connect_authorize.pl?";

    /** The configuration object. */
    private ClientConfig clientConfig;
    /** Scopes. */
    private String[] scopes;
    /** The display value. */
    private String display;
    /** The device value. */
    private Device device;

    /**
     * Initialize this instance.
     */
    public AuthorizationUrlBuilder() {
        super();
        device = Device.PC;
    }

    /**
     * Set the configuration object.
     * @param config The object which has information for the configuration.
     * @return This instance.
     */
    public final AuthorizationUrlBuilder setClientConfig(
            final ClientConfig config) {
        this.clientConfig = config;
        return this;
    }

    /**
     * Retrieve the configuration object.
     * @return The object which has the information of the configuration.
     */
    public final ClientConfig getClientConfig() {
        return clientConfig;
    }

    /**
     * Set the scopes.
     * @param newScopes The array which has scopes you want to access.
     * @return This instance.
     */
    public final AuthorizationUrlBuilder setScopes(final String[] newScopes) {
        scopes = newScopes;
        return this;
    }

    /**
     * Retrieve scopes.
     * @return The array of scopes.
     */
    public final String[] getScopes() {
        return scopes;
    }

    /**
     * Set the display value.
     * @param newDisplay "pc" or "smartphone".
     * @return This instance.
     */
    public final AuthorizationUrlBuilder setDisplay(final String newDisplay) {
        display = newDisplay;
        return this;
    }

    /**
     * Retrieve the display value.
     * @return The display value.
     */
    public final String getDisplay() {
        return display;
    }

    /**
     * Set the device value.
     * @param newDevice The type of a user's device.
     * @return This instance.
     */
    public final AuthorizationUrlBuilder setDevice(final Device newDevice) {
        device = newDevice;
        return this;
    }

    /**
     * Retrieve the device value.
     * @return The device value.
     */
    public final Device getDevice() {
        return device;
    }

    /**
     * Build the URL and return it.
     * @return Built URL.
     */
    public final String build() {
        try {
            StringBuilder sb = new StringBuilder();
            if (device.equals(Device.MOBILE)) {
                sb.append(MIXI_AUTHORIZATION_MOBILE_URL);
            } else {
                sb.append(MIXI_AUTHORIZATION_URL);
            }
            sb.append("client_id=");
            sb.append(URLEncoder.encode(clientConfig.getClientId(), "UTF-8"));
            sb.append("&response_type=code&scope=");
            sb.append(URLEncoder.encode(joinScopes(), "UTF-8"));
            if (device != Device.MOBILE) {
                sb.append("&display=");
                sb.append(display);
            }
            return sb.toString();
        } catch (UnsupportedEncodingException e) {
            throw new IllegalArgumentException(e);
        }
    }

    /**
     * Join scope strings.
     * @return Joined each scopes as one string.
     */
    private String joinScopes() {
        StringBuilder sb = new StringBuilder();
        boolean first = true;
        for (int i = 0; i < scopes.length; i++) {
            if (!first) {
                sb.append(" ");
            } else {
                first = false;
            }
            sb.append(scopes[i]);
        }
        return sb.toString();
    }

}
